import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

public class MyTimer {
    //用一个阻塞队列来组织任务
    private BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    private Object locker = new Object();

    public MyTimer(){

        //创建扫描线程
        Thread thread = new Thread(()->{
            //不断扫描队列中的任务
            while (true){
                try {
                    //1.从队列中取出任务
                    MyTask task = this.queue.take();
                    //2.到没到执行时间
                    long currentTime = System.currentTimeMillis();
                    if (currentTime>= task.getTime()){
                        //时间到了，执行任务
                        task.getRunnable().run();
                    }else {
                        //当前时间与任务执行时间的差
                        long waitTime = task.getTime() - currentTime;
                        //没有到时间就放回队列
                        queue.put(task);
                        synchronized (locker){
                            //加入等时间
                            locker.wait(waitTime);
                        }
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        },"scanThread");
        //启动线程真正去系统中申请资源
        thread.start();

        //创建一个后台线程
        Thread daemonThread = new Thread(()->{
            while (true){
                //定时唤醒
                synchronized (locker){
                    locker.notifyAll();
                }
                //休眠一会
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        });
        daemonThread.setDaemon(true);  //设置成后台线程
        daemonThread.start();  //启动线程
    }

    public void schedule(Runnable runnable,long delay)throws InterruptedException{
        //根据传处的参数，构建一个MyTask
        MyTask task = new MyTask(runnable,delay);
        //把任务放入阻塞队列
        queue.put(task);
        //唤醒等待的线程
        synchronized (locker){
            locker.notifyAll();
        }
    }
}


//用一个类来描述任务及任务执行的时间
class MyTask implements Comparable<MyTask>{

    private Runnable runnable;  //任务
    private long time;  //任务执行的时间

    public MyTask(Runnable runnable,long delay){
        //检验任务不能为空
        if (runnable == null){
            try {
                throw new IllegalAccessException("任务不能为空.");
            }catch (Exception e){

            }

        }
        //时间不能为负
        if (delay<0){
            try {
                throw new IllegalAccessException("执行时间不能小于0.");
            }catch (Exception e) {

            }
        }
        this.runnable = runnable;
        //计算出执行任务的具体时间
        this.time = delay + System.currentTimeMillis();
    }

    public Runnable getRunnable(){
        return runnable;
    }

    public long getTime(){
        return time;
    }

    public int compareTo(MyTask o){
        if (this.getTime()>o.getTime()){
            return 1;
        } else if (this.getTime()<o.getTime()) {
            return -1;
        }else {
            return 0;
        }
    }
}
